home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!gatech!ukma!cwjcc!hal!ncoast!allbery
- From: ljz@fxgrp.UUCP (Lloyd Zusman)
- Newsgroups: comp.sources.misc
- Subject: v04i117: Arbitrary Precision Math Library -- 4 of 5
- Message-ID: <8810051945.AA05747@fxgrp.fx.com>
- Date: 7 Oct 88 00:14:23 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: ljz@fxgrp.UUCP (Lloyd Zusman)
- Lines: 1904
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 117
- Submitted-by: "Lloyd Zusman" <ljz@fxgrp.UUCP>
- Archive-name: apml/Part4
-
- Enclosed you will find the Arbitrary Precision Math Library (4 of 5)
-
- Please post this to the comp.sources.misc newsgroup.
-
- I finally got this into good enough shape to send out to the net. To use,
- just unshar the 5 pieces, read the README file, possibly alter the makefiles
- to conform to your system's conventions, and then type 'make test'.
-
- Good luck!
-
- --
- Lloyd Zusman Internet: ljz@fx.com
- Master Byte Software or ljz%fx.com@ames.arc.nasa.gov
- Los Gatos, California or fxgrp!ljz@ames.arc.nasa.gov
- "We take things well in hand." uucp: ...!ames!fxgrp!ljz
- [ our Internet connection is down: use uucp or mail to the entry above it ]
-
- #--------------------------Cut Here--------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before the "#! /bin/sh" line,
- # then unpack it by saving it in a file and typing "sh file."
- #
- # Wrapped by Lloyd Zusman (ljz) at fxgrp on Wed Oct 5 12:41:51 1988
- #
- # unpacks with default permissions
- #
- # Contents : muldiv.c utils.c
- #
- if `test ! -s muldiv.c`
- then
- echo "x - muldiv.c"
- sed 's/^X//' > muldiv.c << '@\END_OF_FILE_muldiv.c'
- X/******************************************************************************
- X
- X Arbitrary Precision Math Library General Public License
- X (Written October 5, 1988)
- X
- X Copyright (C) 1988 Lloyd Zusman, Master Byte Software, Los
- X Gatos, California. Everyone is permitted to copy and distribute
- X verbatim copies of this license, but changing it is not allowed.
- X You can also use this wording to make the terms for other programs.
- X
- X The wording of this license is based on that of the
- X "GNU EMACS GENERAL PUBLIC LICENSE" by Richard Stallman,
- X Copyright (C) 1985, 1987, 1988, version of February 11, 1988,
- X but since some of the text has been changed, please be sure to
- X READ THIS CAREFULLY!
- X
- X This general public license is intended to give everyone the right
- Xto share the Arbitrary Precision Math Library (hereinafter referred to
- Xas the "APM Library"). To make sure that you get the rights we want
- Xyou to have, I need to make restrictions that forbid anyone to deny
- Xyou these rights or to ask you to surrender the rights.
- X
- X Specifically, we want to make sure that you have the right to give
- Xaway copies of the APM Library, that you receive source code or else
- Xcan get it if you want it, that you can change the APM Library or use
- Xpieces of it in new programs, and that you know you can do these
- Xthings.
- X
- X To make sure that everyone has such rights, we have to forbid you to
- Xdeprive anyone else of these rights. For example, if you distribute
- Xcopies of the APM Library, you must give the recipients all the
- Xrights that you have. You must make sure that they, too, receive or
- Xcan get the source code. And you must tell them their rights.
- X
- X Also, for our own protection, we must make certain that everyone
- Xfinds out that there is no warranty for the APM Library. If the APM
- XLibrary is modified by someone else and passed on, we want its
- Xrecipients to know that what they have is not what we distributed, so
- Xthat any problems introduced by others will not reflect on our
- Xreputation.
- X
- X Therefore we (Lloyd Zusman and Master Byte Software) make the
- Xfollowing terms which say what you must do to be allowed to
- Xdistribute or change the APM Library.
- X
- X COPYING POLICIES
- X
- X1. You may copy and distribute verbatim copies of the APM Library
- Xsource code as you receive it, in any medium, provided that you
- Xconspicuously and appropriately publish on each copy a valid copyright
- Xnotice "Copyright (C) 1988 Lloyd Zusman, Master Byte Software, Los
- XGatos, California" (or with whatever year is appropriate); keep intact
- Xthe notices on all files that refer to this License Agreement and to
- Xthe absence of any warranty; and give any other recipients of the the
- XAPM Library program a copy of this License Agreement along with the
- Xprogram. You may charge a distribution fee for the physical act of
- Xtransferring a copy.
- X
- X 2. You may modify your copy or copies of the APM Library source code or
- Xany portion of it, and copy and distribute such modifications under
- Xthe terms of Paragraph 1 above, provided that you also do the following:
- X
- X a) cause the modified files to carry prominent notices stating
- X that you changed the files and the date of any change; and
- X
- X b) cause the whole of any work that you distribute or publish, that in
- X whole or in part contains or is a derivative of the APM Library or any
- X part thereof, to be licensed to all third parties on terms identical
- X to those contained in this License Agreement (except that you may
- X choose to grant more extensive warranty protection to some or all
- X third parties, at your option).
- X
- X c) You may charge a distribution fee for the physical act of
- X transferring a copy, and you may at your option offer warranty
- X protection in exchange for a fee.
- X
- X d) You may not charge a license fee for the whole of any work that
- X you distribute or publish, that in whole or in part contains or is
- X a derivative of the APM library or any part thereof, without the
- X express written permission of Lloyd Zusman and Master Byte Software;
- X whether this permission is granted for free or in return for goods
- X services, royalties, or other compensation will be determined
- X solely by Lloyd Zusman and Master Byte Software.
- X
- XMere aggregation of another unrelated program with this program (or its
- Xderivative) on a volume of a storage or distribution medium does not bring
- Xthe other program under the scope of these terms.
- X
- X 3. You may copy and distribute the APM Library (or a portion or
- Xderivative of it, under Paragraph 2) in object code or executable form
- Xunder all the terms of Paragraphs 1 and 2 above provided that you also
- Xdo one of the following:
- X
- X a) accompany it with the complete corresponding machine-readable
- X source code, which must be distributed under the terms of
- X Paragraphs 1 and 2 above; or,
- X
- X b) accompany it with a written offer, valid for at least three
- X years, to give any third party free (except for a nominal
- X shipping charge) a complete machine-readable copy of the
- X corresponding source code, to be distributed under the terms of
- X Paragraphs 1 and 2 above; or,
- X
- X c) accompany it with the information you received as to where the
- X corresponding source code may be obtained. (This alternative is
- X allowed only for noncommercial distribution and only if you
- X received the program in object code or executable form alone.)
- X
- XFor an executable file, complete source code means all the source code
- Xfor all modules it contains; but, as a special exception, it need not
- Xinclude source code for modules which are standard libraries that
- Xaccompany the operating system on which the executable file runs.
- X
- X 4. You may not copy, sublicense, distribute or transfer the APM
- XLibrary except as expressly provided under this License Agreement.
- XAny attempt otherwise to copy, sublicense, distribute or transfer the
- XAPM Library is void and your rights to use the APM Library under this
- XLicense agreement shall be automatically terminated. However, parties
- Xwho have received computer software programs from you with this
- XLicense Agreement will not have their licenses terminated so long as
- Xsuch parties remain in full compliance.
- X
- X 5. If you wish to incorporate parts of the APM Library into other
- Xprograms whose distribution conditions are different, write to Lloyd
- XZusman at Master Byte Software. We have not yet worked out a simple
- Xrule that can be stated here, but we will often permit this. We will
- Xbe guided by the goals of (1) preserving the free status of all
- Xderivatives of our free software; of (2) promoting the sharing and
- Xreuse of software; and of (3) not allowing anyone to profit from the
- Xuse of our software without us also having the opportunity to share
- Xin these profits.
- X
- XYour comments and suggestions about our licensing policies and our
- Xsoftware are welcome! Please contact Lloyd Zusman, Master Byte
- XSoftware, 127 Wilder Ave., Los Gatos, California 95030, or call
- X(408) 395-5693.
- X
- X NO WARRANTY
- X
- X BECAUSE THE APM LIBRARY IS LICENSED FREE OF CHARGE, WE PROVIDE
- XABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE
- XLAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, MASTER BYTE SOFTWARE,
- XLLOYD ZUSMAN AND/OR OTHER PARTIES PROVIDE THE APM LIBRARY "AS IS"
- XWITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
- XBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- XFITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
- XAND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE THE APM
- XLIBRARY PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
- XSERVICING, REPAIR OR CORRECTION.
- X
- X IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL MASTER BYTE
- XSOFTWARE, LLOYD ZUSMAN, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
- XREDISTRIBUTE THE APM LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
- XDAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
- XINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- XINABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- XBEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- XFAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
- XMASTER BYTE SOFTWARE) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF
- XTHE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
- X
- X******************************************************************************/
- X
- X
- X/*
- X * Multiplication and division routines for the APM library.
- X *
- X * $Log: muldiv.c,v $
- X * Revision 1.0 88/10/05 12:38:15 ljz
- X * Initial release.
- X *
- X */
- X#ifndef lint
- Xstatic char rcsid[] = "$Header: muldiv.c,v 1.0 88/10/05 12:38:15 ljz Exp $";
- X#endif /* ! lint */
- X
- X#include <stdio.h>
- X#include "apm.h"
- X#include "apmlocal.h"
- X
- Xint
- Xapm_multiply(result, num1, num2)
- XAPM result;
- XAPM num1;
- XAPM num2;
- X{
- X int length1;
- X int length2;
- X int len;
- X int dp;
- X int n1;
- X int n2;
- X int sum;
- X short sign;
- X short base;
- X short carry;
- X long tempval;
- X
- X apm_errno = APM_OK;
- X
- X ERR_RETURN(APM_val_format(result));
- X ERR_RETURN(apm_validate(num1));
- X ERR_RETURN(apm_validate(num2));
- X
- X if (num1->base != num2->base) {
- X return (APM_error(APM_EBASE));
- X }
- X
- X if (result == num1 || result == num2) {
- X return (APM_error(APM_EOVERLAP));
- X }
- X
- X base = num1->base;
- X
- X sign = SIGNOF(num1->sign) * SIGNOF(num2->sign);
- X
- X ERR_RETURN(APM_trim(num1, 1, 1));
- X ERR_RETURN(APM_trim(num2, 1, 1));
- X
- X length1 = num1->length;
- X length2 = num2->length;
- X
- X len = length1 + length2;
- X dp = num1->dp + num2->dp;
- X
- X ERR_RETURN(APM_size(result, len));
- X
- X APM_zero_shorts(result->data, len);
- X
- X for (n1 = 0; n1 < length1; ++n1) {
- X carry = 0;
- X sum = n1;
- X for (n2 = 0; n2 < length2; ++n2, ++sum) {
- X tempval = num1->data[n1];
- X tempval *= num2->data[n2];
- X tempval += result->data[sum] + carry;
- X result->data[sum] =
- X (short)(tempval % base);
- X carry =
- X (short)(tempval / base);
- X }
- X result->data[sum] = carry;
- X }
- X
- X result->length = len;
- X result->dp = dp;
- X result->base = base;
- X result->sign = sign;
- X
- X return (APM_error(APM_trim(result, 1, 1)));
- X}
- X
- X/*
- X * For division, I use the algorithm described in Knuth, "The Art of
- X * Computer Programming, Volume 2, Seminumerical Algorithms", second
- X * edition, pp. 255-260.
- X */
- Xint
- Xapm_divide(result, frac_precision, remainder, num1, num2)
- XAPM result;
- Xint frac_precision;
- XAPM remainder;
- XAPM num1;
- XAPM num2;
- X{
- X static APM temp = (APM)NULL;
- X static short *dividend = (short *)NULL;
- X static int dividendLength = 0;
- X static short *divisor = (short *)NULL;
- X static short *xdivisor = (short *)NULL;
- X static int divisorLength = 0;
- X
- X int i;
- X int j;
- X int n;
- X int uJ;
- X int vJ;
- X int M;
- X int N;
- X int MplusN;
- X int Nplus1;
- X int MplusNplus1;
- X int length1;
- X int length2;
- X int offset;
- X int left;
- X int frac;
- X short divN1;
- X short divN2;
- X short sign;
- X short base;
- X short scaleFactor;
- X short borrow;
- X short qHat;
- X long temp1;
- X long temp2;
- X long temp3;
- X
- X apm_errno = APM_OK;
- X
- X if (frac_precision <= 0) {
- X return (APM_set_errno(APM_EPARM));
- X }
- X
- X ERR_RETURN(APM_val_format(result));
- X if (remainder != NULL) {
- X ERR_RETURN(APM_val_format(remainder));
- X }
- X ERR_RETURN(apm_validate(num1));
- X ERR_RETURN(apm_validate(num2));
- X
- X if (result == remainder || result == num1 || result == num2) {
- X return (APM_error(APM_EOVERLAP));
- X }
- X if (remainder == num1 || remainder == num2) {
- X return (APM_error(APM_EOVERLAP));
- X }
- X
- X base = num1->base;
- X
- X ERR_RETURN(APM_trim(num2, 1, 1));
- X if (num2->length <= 0) {
- X /*
- X * Division by zero.
- X */
- X result->length = 0;
- X result->dp = 0;
- X result->base = base;
- X if (remainder != (APM)NULL) {
- X remainder->length = 0;
- X remainder->dp = 0;
- X remainder->base = base;
- X }
- X return (APM_error(APM_WDIVBYZERO));
- X }
- X
- X ERR_RETURN(APM_trim(num1, 1, 1));
- X if (num1->length <= 0) {
- X /*
- X * Dividend is zero, so result is zero.
- X */
- X result->length = 0;
- X result->dp = 0;
- X result->base = base;
- X if (remainder != (APM)NULL) {
- X remainder->length = 0;
- X remainder->dp = 0;
- X remainder->base = base;
- X }
- X return (APM_OK);
- X }
- X
- X sign = num1->sign * num2->sign;
- X
- X length1 = num1->length;
- X length2 = num2->length;
- X for (offset = length2; offset > 0; --offset) {
- X if (num2->data[offset - 1] != 0) {
- X break;
- X }
- X }
- X
- X offset = length2 - offset;
- X
- X frac = frac_precision;
- X if (base == SPECIAL_BASE) {
- X frac = (frac + (SPECIAL_SCALE - 1)) / SPECIAL_SCALE;
- X }
- X
- X
- X left = (length1 - num1->dp) - (length2 - num1->dp);
- X if (left < 0) {
- X left = 0;
- X }
- X
- X M = frac + left + 1;
- X if (M < length1) {
- X M = length1;
- X }
- X
- X N = (length2 - offset) + 1;
- X Nplus1 = N + 1;
- X MplusN = M + N;
- X MplusNplus1 = MplusN + 1;
- X
- X if (temp == (APM)NULL) {
- X temp = APM_alloc();
- X if (temp == (APM)NULL) {
- X return (APM_error(APM_ENOMEM));
- X }
- X }
- X
- X ERR_RETURN(APM_size(temp, M + 1));
- X
- X if (MplusNplus1 > dividendLength) {
- X int xlen = MplusNplus1;
- X if (xlen < 8) {
- X xlen = 8;
- X }
- X if (dividendLength < 1) {
- X dividend = (short *)APM_alloc_mem(NULL, xlen,
- X sizeof (short));
- X }
- X else {
- X dividend = (short *)APM_alloc_mem(dividend, xlen,
- X sizeof (short));
- X }
- X if (dividend == (short *)NULL) {
- X return (APM_error(APM_ENOMEM));
- X }
- X dividendLength = xlen;
- X }
- X
- X if (Nplus1 > divisorLength) {
- X int xlen = Nplus1;
- X if (xlen < 8) {
- X xlen = 8;
- X }
- X if (divisorLength < 1) {
- X divisor = (short *)APM_alloc_mem(NULL, xlen,
- X sizeof (short));
- X }
- X else {
- X divisor = (short *)APM_alloc_mem(divisor, xlen,
- X sizeof (short));
- X }
- X if (divisor == (short *)NULL) {
- X return (APM_error(APM_ENOMEM));
- X }
- X if (divisorLength < 1) {
- X xdivisor = (short *)APM_alloc_mem(NULL, xlen,
- X sizeof (short));
- X }
- X else {
- X xdivisor = (short *)APM_alloc_mem(xdivisor, xlen,
- X sizeof (short));
- X }
- X if (xdivisor == (short *)NULL) {
- X return (APM_error(APM_ENOMEM));
- X }
- X divisorLength = xlen;
- X }
- X
- X i = MplusN - length1;
- X
- X APM_zero_shorts(dividend, i);
- X APM_copy_shorts(÷nd[i], num1->data, length1);
- X
- X divisor[0] = 0;
- X APM_copy_shorts(&divisor[1], num2->data, length2 - offset);
- X
- X /*
- X * Knuth: step D1.
- X */
- X scaleFactor = base / (divisor[N - 1] + 1);
- X if (scaleFactor <= 1) {
- X dividend[MplusN] = 0;
- X }
- X else {
- X dividend[MplusN] = APM_scalar_mul(dividend, dividend,
- X MplusN,
- X scaleFactor, base);
- X APM_scalar_mul(divisor, divisor, N, scaleFactor, base);
- X }
- X
- X divN1 = divisor[N - 1];
- X divN2 = divisor[N - 2];
- X
- X /*
- X * Knuth: steps D2 and D7.
- X */
- X for (j = 0, vJ = M, uJ = MplusN; j <= M; ++j, --vJ, --uJ) {
- X /*
- X * Knuth: step D3.
- X */
- X temp1 = dividend[uJ];
- X temp1 *= base;
- X temp1 += dividend[uJ - 1];
- X
- X if (dividend[uJ] == divN1) {
- X qHat = base - 1;
- X }
- X else {
- X temp2 = temp1 / divN1;
- X qHat = (short)temp2;
- X }
- X
- X for (;;) {
- X temp2 = divN2;
- X temp2 *= qHat;
- X
- X temp3 = divN1;
- X temp3 *= qHat;
- X temp3 = temp1 - temp3;
- X temp3 *= base;
- X temp3 += dividend[uJ - 2];
- X
- X if (temp2 > temp3) {
- X --qHat;
- X }
- X else {
- X break;
- X }
- X }
- X
- X /*
- X * Knuth: step D4.
- X */
- X xdivisor[N] = APM_scalar_mul(xdivisor, divisor, N, qHat,
- X base);
- X borrow = APM_array_sub(&(dividend[vJ]), xdivisor,
- X Nplus1, base);
- X
- X /*
- X * Knuth: step D5.
- X */
- X if (borrow == 0) {
- X temp->data[vJ] = qHat;
- X }
- X else {
- X /*
- X * Knuth: step D6.
- X */
- X temp->data[vJ] = qHat - 1;
- X divisor[N] = 0;
- X APM_array_add(&(dividend[vJ]), divisor, Nplus1, base);
- X }
- X }
- X
- X /*
- X * Knuth: step D8.
- X */
- X temp->length = M + 1;
- X temp->dp = (M - offset) -
- X ((length1 - num1->dp) - (length2 - num2->dp));
- X temp->base = base;
- X temp->sign = sign;
- X
- X ERR_RETURN(apm_round(result, temp, frac_precision));
- X ERR_RETURN(APM_trim(result, 1, 1));
- X
- X if (remainder != (APM)NULL) {
- X ERR_RETURN(APM_size(temp, length2));
- X if (scaleFactor > 1) {
- X ERR_RETURN(APM_scalar_div(temp, ÷nd[1],
- X length2,
- X num2->dp,
- X num2->sign,
- X base, scaleFactor));
- X }
- X else {
- X temp->length = length2;
- X temp->dp = num2->dp;
- X temp->sign = num2->sign;
- X temp->base = base;
- X APM_copy_shorts(temp->data, ÷nd[1], length2);
- X }
- X ERR_RETURN(apm_round(remainder, temp, frac_precision));
- X ERR_RETURN(APM_trim(remainder, 1, 1));
- X }
- X
- X return (APM_OK);
- X}
- @\END_OF_FILE_muldiv.c
- else
- echo "shar: Will not over write muldiv.c"
- fi
- if `test ! -s utils.c`
- then
- echo "x - utils.c"
- sed 's/^X//' > utils.c << '@\END_OF_FILE_utils.c'
- X/******************************************************************************
- X
- X Arbitrary Precision Math Library General Public License
- X (Written October 5, 1988)
- X
- X Copyright (C) 1988 Lloyd Zusman, Master Byte Software, Los
- X Gatos, California. Everyone is permitted to copy and distribute
- X verbatim copies of this license, but changing it is not allowed.
- X You can also use this wording to make the terms for other programs.
- X
- X The wording of this license is based on that of the
- X "GNU EMACS GENERAL PUBLIC LICENSE" by Richard Stallman,
- X Copyright (C) 1985, 1987, 1988, version of February 11, 1988,
- X but since some of the text has been changed, please be sure to
- X READ THIS CAREFULLY!
- X
- X This general public license is intended to give everyone the right
- Xto share the Arbitrary Precision Math Library (hereinafter referred to
- Xas the "APM Library"). To make sure that you get the rights we want
- Xyou to have, I need to make restrictions that forbid anyone to deny
- Xyou these rights or to ask you to surrender the rights.
- X
- X Specifically, we want to make sure that you have the right to give
- Xaway copies of the APM Library, that you receive source code or else
- Xcan get it if you want it, that you can change the APM Library or use
- Xpieces of it in new programs, and that you know you can do these
- Xthings.
- X
- X To make sure that everyone has such rights, we have to forbid you to
- Xdeprive anyone else of these rights. For example, if you distribute
- Xcopies of the APM Library, you must give the recipients all the
- Xrights that you have. You must make sure that they, too, receive or
- Xcan get the source code. And you must tell them their rights.
- X
- X Also, for our own protection, we must make certain that everyone
- Xfinds out that there is no warranty for the APM Library. If the APM
- XLibrary is modified by someone else and passed on, we want its
- Xrecipients to know that what they have is not what we distributed, so
- Xthat any problems introduced by others will not reflect on our
- Xreputation.
- X
- X Therefore we (Lloyd Zusman and Master Byte Software) make the
- Xfollowing terms which say what you must do to be allowed to
- Xdistribute or change the APM Library.
- X
- X COPYING POLICIES
- X
- X1. You may copy and distribute verbatim copies of the APM Library
- Xsource code as you receive it, in any medium, provided that you
- Xconspicuously and appropriately publish on each copy a valid copyright
- Xnotice "Copyright (C) 1988 Lloyd Zusman, Master Byte Software, Los
- XGatos, California" (or with whatever year is appropriate); keep intact
- Xthe notices on all files that refer to this License Agreement and to
- Xthe absence of any warranty; and give any other recipients of the the
- XAPM Library program a copy of this License Agreement along with the
- Xprogram. You may charge a distribution fee for the physical act of
- Xtransferring a copy.
- X
- X 2. You may modify your copy or copies of the APM Library source code or
- Xany portion of it, and copy and distribute such modifications under
- Xthe terms of Paragraph 1 above, provided that you also do the following:
- X
- X a) cause the modified files to carry prominent notices stating
- X that you changed the files and the date of any change; and
- X
- X b) cause the whole of any work that you distribute or publish, that in
- X whole or in part contains or is a derivative of the APM Library or any
- X part thereof, to be licensed to all third parties on terms identical
- X to those contained in this License Agreement (except that you may
- X choose to grant more extensive warranty protection to some or all
- X third parties, at your option).
- X
- X c) You may charge a distribution fee for the physical act of
- X transferring a copy, and you may at your option offer warranty
- X protection in exchange for a fee.
- X
- X d) You may not charge a license fee for the whole of any work that
- X you distribute or publish, that in whole or in part contains or is
- X a derivative of the APM library or any part thereof, without the
- X express written permission of Lloyd Zusman and Master Byte Software;
- X whether this permission is granted for free or in return for goods
- X services, royalties, or other compensation will be determined
- X solely by Lloyd Zusman and Master Byte Software.
- X
- XMere aggregation of another unrelated program with this program (or its
- Xderivative) on a volume of a storage or distribution medium does not bring
- Xthe other program under the scope of these terms.
- X
- X 3. You may copy and distribute the APM Library (or a portion or
- Xderivative of it, under Paragraph 2) in object code or executable form
- Xunder all the terms of Paragraphs 1 and 2 above provided that you also
- Xdo one of the following:
- X
- X a) accompany it with the complete corresponding machine-readable
- X source code, which must be distributed under the terms of
- X Paragraphs 1 and 2 above; or,
- X
- X b) accompany it with a written offer, valid for at least three
- X years, to give any third party free (except for a nominal
- X shipping charge) a complete machine-readable copy of the
- X corresponding source code, to be distributed under the terms of
- X Paragraphs 1 and 2 above; or,
- X
- X c) accompany it with the information you received as to where the
- X corresponding source code may be obtained. (This alternative is
- X allowed only for noncommercial distribution and only if you
- X received the program in object code or executable form alone.)
- X
- XFor an executable file, complete source code means all the source code
- Xfor all modules it contains; but, as a special exception, it need not
- Xinclude source code for modules which are standard libraries that
- Xaccompany the operating system on which the executable file runs.
- X
- X 4. You may not copy, sublicense, distribute or transfer the APM
- XLibrary except as expressly provided under this License Agreement.
- XAny attempt otherwise to copy, sublicense, distribute or transfer the
- XAPM Library is void and your rights to use the APM Library under this
- XLicense agreement shall be automatically terminated. However, parties
- Xwho have received computer software programs from you with this
- XLicense Agreement will not have their licenses terminated so long as
- Xsuch parties remain in full compliance.
- X
- X 5. If you wish to incorporate parts of the APM Library into other
- Xprograms whose distribution conditions are different, write to Lloyd
- XZusman at Master Byte Software. We have not yet worked out a simple
- Xrule that can be stated here, but we will often permit this. We will
- Xbe guided by the goals of (1) preserving the free status of all
- Xderivatives of our free software; of (2) promoting the sharing and
- Xreuse of software; and of (3) not allowing anyone to profit from the
- Xuse of our software without us also having the opportunity to share
- Xin these profits.
- X
- XYour comments and suggestions about our licensing policies and our
- Xsoftware are welcome! Please contact Lloyd Zusman, Master Byte
- XSoftware, 127 Wilder Ave., Los Gatos, California 95030, or call
- X(408) 395-5693.
- X
- X NO WARRANTY
- X
- X BECAUSE THE APM LIBRARY IS LICENSED FREE OF CHARGE, WE PROVIDE
- XABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE
- XLAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, MASTER BYTE SOFTWARE,
- XLLOYD ZUSMAN AND/OR OTHER PARTIES PROVIDE THE APM LIBRARY "AS IS"
- XWITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
- XBUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- XFITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY
- XAND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE THE APM
- XLIBRARY PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
- XSERVICING, REPAIR OR CORRECTION.
- X
- X IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL MASTER BYTE
- XSOFTWARE, LLOYD ZUSMAN, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND
- XREDISTRIBUTE THE APM LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
- XDAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL,
- XINCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- XINABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
- XBEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A
- XFAILURE OF THE PROGRAM TO OPERATE WITH PROGRAMS NOT DISTRIBUTED BY
- XMASTER BYTE SOFTWARE) THE PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF
- XTHE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
- X
- X******************************************************************************/
- X
- X
- X/*
- X * Low level utilities for the APM library. The user never should call
- X * any of these directly.
- X *
- X * $Log: utils.c,v $
- X * Revision 1.0 88/10/05 12:38:16 ljz
- X * Initial release.
- X *
- X */
- X#ifndef lint
- Xstatic char rcsid[] = "$Header: utils.c,v 1.0 88/10/05 12:38:16 ljz Exp $";
- X#endif /* ! lint */
- X
- X#include <stdio.h>
- X#include <varargs.h>
- X#include "apm.h"
- X#include "apmlocal.h"
- X
- Xint apm_errno = APM_OK;
- Xint (*APM_error_func)() = (int (*)())NULL;
- Xint APM_line = 0;
- Xchar *APM_file = "";
- Xchar *APM_func_name = "";
- X
- Xstatic char APM_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- X
- X#define MAX_BASE ((sizeof (APM_digits) / sizeof (APM_digits[0])) - 1)
- X
- Xchar *
- XAPM_error_message(code)
- Xint code;
- X{
- X static char localMessage[80];
- X char *message;
- X
- X switch (code) {
- X case APM_ENOMEM:
- X message = "memory allocation failed";
- X break;
- X case APM_WNULL:
- X message = "null argument";
- X break;
- X case APM_WDIVBYZERO:
- X message = "division by zero";
- X break;
- X case APM_WTRUNC:
- X message = "result truncated";
- X break;
- X case APM_WNOALLOC:
- X message = "attempt to free unallocated APM value";
- X break;
- X case APM_EPARM:
- X message = "invalid function parameter";
- X break;
- X case APM_ENULL:
- X message = "null APM value";
- X break;
- X case APM_EBADVAL:
- X message = "bad APM value";
- X break;
- X case APM_ENULLVAL:
- X message = "null value";
- X break;
- X case APM_EFMT:
- X message = "invalid string format";
- X break;
- X case APM_EBASE:
- X message = "invalid base";
- X break;
- X case APM_ESIZE:
- X message = "destination size is too small";
- X break;
- X case APM_EOVERLAP:
- X message = "result overlaps one or more operands";
- X break;
- X default:
- X sprintf(localMessage, "unknown error code: %d", code);
- X message = localMessage;
- X break;
- X }
- X
- X return (message);
- X}
- X
- Xint
- XAPM_set_errno(code)
- Xint code;
- X{
- X apm_errno = code;
- X return (code);
- X}
- X
- Xint
- XAPM_error(code)
- Xint code;
- X{
- X code = APM_set_errno(code);
- X
- X if (code != APM_OK && APM_error_func != (int (*)())NULL) {
- X code = (*APM_error_func)(code,
- X APM_error_message(code),
- X APM_file, APM_line,
- X APM_func_name);
- X }
- X return (code);
- X}
- X
- Xchar *
- XAPM_trim_string(string)
- Xchar *string;
- X{
- X char *orig = string;
- X char *sp = string;
- X
- X if (string != NULL) {
- X for (; *string != '\0'; ++string) {
- X if (*string != ' ' && *string != '\t') {
- X sp = string + 1;
- X }
- X }
- X *sp = '\0';
- X }
- X
- X return (orig);
- X}
- X
- Xchar *
- XAPM_left_justify(string, ignore)
- Xchar *string;
- Xchar *ignore;
- X{
- X if (string != NULL && ignore != NULL) {
- X for (; *string != '\0'; ++string) {
- X if (APM_index(ignore, *string) == NULL) {
- X break;
- X }
- X }
- X }
- X
- X return (string);
- X}
- X
- Xint
- XAPM_val_format(apm)
- XAPM apm;
- X{
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X if (apm->magic != APM_MAGIC) {
- X return (APM_set_errno(APM_EBADVAL));
- X }
- X return (APM_OK);
- X}
- X
- Xint
- XAPM_val_base(base)
- Xshort base;
- X{
- X apm_errno = APM_OK;
- X
- X if (base == SPECIAL_BASE) {
- X return (APM_OK);
- X }
- X
- X if (base < 2 || base > MAX_BASE) {
- X return (APM_set_errno(APM_EBASE));
- X }
- X
- X return (APM_OK);
- X}
- X
- Xshort
- XAPM_get_digit(ch, base)
- Xchar ch;
- Xshort base;
- X{
- X int ercode;
- X short idx;
- X
- X ercode = APM_val_base(base);
- X if (ercode < APM_OK) {
- X return (APM_set_errno(ercode));
- X }
- X
- X if (base == SPECIAL_BASE) {
- X base = 10;
- X }
- X
- X for (idx = 0; idx < base; ++idx) {
- X if (ch == APM_digits[idx]) {
- X return (idx);
- X }
- X }
- X
- X return (APM_set_errno(APM_EBASE));
- X}
- X
- Xint
- XAPM_radix_pos(string, base)
- Xchar *string;
- Xshort base;
- X{
- X int dp = -1;
- X int nodigits = 1;
- X int pos = 0;
- X int ercode;
- X
- X if (string == NULL) {
- X return (APM_set_errno(APM_ENULLVAL));
- X }
- X ercode = APM_val_base(base);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X for (; string[pos] != '\0'; ++pos) {
- X if (string[pos] == '.') {
- X if (dp >= 0) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X else {
- X dp = pos;
- X }
- X }
- X else if (APM_get_digit(string[pos], base) < 0) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X else {
- X nodigits = 0;
- X }
- X }
- X
- X if (nodigits) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X
- X return (dp + 1);
- X}
- X
- Xint
- XAPM_shift(num, scaleFactor)
- XAPM num;
- Xint scaleFactor;
- X{
- X int ercode;
- X
- X apm_errno = APM_OK;
- X
- X if (scaleFactor == 0) {
- X return (APM_OK);
- X }
- X if (num->base != 0 && num->base != SPECIAL_BASE) {
- X num->dp -= scaleFactor;
- X }
- X else {
- X /*
- X * The following code assumes that
- X * (-X) % Y == -(X % Y).
- X */
- X int factor = scaleFactor / SPECIAL_SCALE;
- X int n = scaleFactor % SPECIAL_SCALE;
- X
- X if (scaleFactor < 0) {
- X --factor;
- X n += SPECIAL_SCALE;
- X }
- X num->dp -= factor;
- X if (n > 0) {
- X int multiplier = 1;
- X while (n-- > 0) {
- X multiplier *= 10;
- X }
- X n = (num->length)++;
- X ercode = APM_size(num, num->length);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X num->data[n] = APM_scalar_mul(num->data,
- X num->data, n,
- X multiplier,
- X num->base);
- X }
- X }
- X return (APM_trim(num, 1, 1));
- X}
- X
- Xint
- XAPM_trimlead(apm)
- XAPM apm;
- X{
- X int n;
- X int ercode;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (apm->data == NULL) {
- X apm->length = 0;
- X return (APM_OK);
- X }
- X
- X ercode = APM_normalize(apm);
- X if (ercode < APM_OK) {
- X return (APM_set_errno(ercode));
- X }
- X
- X for (n = apm->length; n > 0; --n) {
- X if (apm->data[n - 1] != 0) {
- X break;
- X }
- X }
- X
- X if (n < apm->length) {
- X apm->length = n;
- X }
- X
- X return (APM_OK);
- X}
- X
- Xint
- XAPM_trimtrail(apm)
- XAPM apm;
- X{
- X int n;
- X int ercode;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (apm->data == NULL) {
- X apm->length = 0;
- X apm->dp = 0;
- X return (APM_OK);
- X }
- X
- X ercode = APM_normalize(apm);
- X if (ercode < APM_OK) {
- X return (APM_set_errno(ercode));
- X }
- X
- X for (n = 0; n < apm->dp; ++n) {
- X if (apm->data[n] != 0) {
- X break;
- X }
- X }
- X
- X if (n == 0) { /* no trailing zeros */
- X return (APM_OK);
- X }
- X
- X /*
- X * Shift down by 'n', subtracting this from apm->length and
- X * apm->dp.
- X */
- X apm->length -= n;
- X apm->dp -= n;
- X APM_copy_shorts(apm->data, &(apm->data[n]), apm->length);
- X APM_zero_shorts(&(apm->data[apm->length]), n);
- X
- X return (APM_OK);
- X}
- X
- Xint
- XAPM_trim(apm, lead, trail)
- XAPM apm;
- Xint lead;
- Xint trail;
- X{
- X int ercode = APM_OK;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (ercode >= APM_OK && lead) {
- X ercode = APM_trimlead(apm);
- X }
- X
- X if (ercode >= APM_OK && trail) {
- X ercode = APM_trimtrail(apm);
- X }
- X
- X if (ercode >= APM_OK) {
- X ercode = APM_normalize(apm);
- X }
- X
- X return (APM_set_errno(ercode));
- X}
- X
- Xint
- XAPM_normalize(value)
- XAPM value;
- X{
- X static short *localData = (short *)NULL;
- X static int localLen = 0;
- X int len;
- X int dp;
- X int offset;
- X int ercode;
- X
- X apm_errno = APM_OK;
- X
- X ercode = APM_val_format(value);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X ercode = APM_val_base(value->base);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X if (value->dp >= 0 && value->length >= value->dp) {
- X return (APM_OK);
- X }
- X
- X len = value->length;
- X if (value->length < value->dp) {
- X len = value->dp;
- X dp = value->dp;
- X offset = 0;
- X }
- X else if (value->dp < 0) {
- X len = value->length - value->dp;
- X dp = 0;
- X offset = -(value->dp);
- X }
- X else {
- X len = value->length;
- X dp = value->dp;
- X offset = 0;
- X }
- X
- X if (len > localLen) {
- X int xlen = len;
- X if (xlen < 8) {
- X xlen = 8;
- X }
- X localData = (short *)APM_alloc_mem(localLen < 1 ?
- X NULL : localData,
- X xlen, sizeof (short));
- X if (localData == (short *)NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X localLen = xlen;
- X }
- X
- X APM_zero_shorts(localData, len);
- X APM_copy_shorts(localData + offset, value->data, value->length);
- X
- X ercode = APM_size(value, len);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X APM_copy_shorts(value->data, localData, len);
- X
- X value->length = len;
- X value->dp = dp;
- X
- X return (APM_OK);
- X}
- X
- Xint
- XAPM_setdp(result, value, dp)
- XAPM result;
- XAPM value;
- Xint dp;
- X{
- X int oldlen;
- X int newlen;
- X int voffset;
- X int roffset;
- X int ercode;
- X
- X apm_errno = APM_OK;
- X
- X ercode = APM_val_format(value);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X ercode = APM_val_base(value->base);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X if (result == value) {
- X return (APM_set_errno(APM_EOVERLAP));
- X }
- X
- X ercode = APM_normalize(value);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X if (dp < 0) {
- X dp = value->dp;
- X }
- X
- X oldlen = newlen = value->length;
- X
- X if (dp <= value->dp) {
- X voffset = value->dp - dp;
- X roffset = 0;
- X oldlen -= voffset;
- X }
- X else {
- X voffset = 0;
- X roffset = dp - value->dp;
- X newlen += roffset;
- X }
- X
- X ercode = APM_size(result, newlen);
- X if (ercode < APM_OK) {
- X return(ercode);
- X }
- X
- X APM_zero_shorts(result->data, newlen);
- X APM_copy_shorts(result->data + roffset, value->data + voffset, oldlen);
- X
- X result->sign = SIGNOF(value->sign);
- X result->base = value->base;
- X result->length = newlen;
- X result->dp = dp;
- X return (APM_OK);
- X}
- X
- Xint
- XAPM_norm_to_spec(apm)
- XAPM apm;
- X{
- X static APM localApm = (APM)NULL;
- X int length;
- X int locallen;
- X int localdp;
- X int ercode;
- X int n;
- X short sign;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (apm->base != 10) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X
- X length = apm->length;
- X sign = SIGNOF(apm->sign);
- X locallen = length;
- X localdp = ((apm->dp + (SPECIAL_SCALE - 1)) / SPECIAL_SCALE)
- X * SPECIAL_SCALE;
- X locallen += (localdp - apm->dp);
- X locallen = ((locallen + (SPECIAL_SCALE - 1)) / SPECIAL_SCALE)
- X * SPECIAL_SCALE;
- X
- X if (localApm == (APM)NULL) {
- X localApm = APM_alloc();
- X if (localApm == (APM)NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X }
- X ercode = APM_size(localApm, locallen / SPECIAL_SCALE);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X for (n = 0; n < locallen; n += SPECIAL_SCALE) {
- X int value = 0;
- X int tn = n + (apm->dp - localdp);
- X if (tn >= 0 && tn < length) {
- X value += apm->data[tn];
- X }
- X ++tn;
- X if (tn >= 0 && tn < length) {
- X value += apm->data[tn] * 10;
- X }
- X ++tn;
- X if (tn >= 0 && tn < length) {
- X value += apm->data[tn] * 100;
- X }
- X ++tn;
- X if (tn >= 0 && tn < length) {
- X value += apm->data[tn] * 1000;
- X }
- X localApm->data[n / SPECIAL_SCALE] = value;
- X }
- X localApm->length = locallen / SPECIAL_SCALE;
- X localApm->dp = localdp / SPECIAL_SCALE;
- X localApm->sign = sign;
- X localApm->base = SPECIAL_BASE;
- X
- X ercode = apm_assign(apm, localApm);
- X
- X return (ercode);
- X}
- X
- Xint
- XAPM_spec_to_norm(apm)
- XAPM apm;
- X{
- X static APM localApm = (APM)NULL;
- X int length;
- X int locallen;
- X int n;
- X int ercode;
- X short sign;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (apm->base != SPECIAL_BASE) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X
- X ercode = APM_trim(apm, 1, 1);
- X if (ercode < APM_OK) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X
- X length = apm->length;
- X sign = SIGNOF(apm->sign);
- X if (localApm == (APM)NULL) {
- X localApm = APM_alloc();
- X if (localApm == (APM)NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X }
- X locallen = length * SPECIAL_SCALE;
- X ercode = APM_size(localApm, locallen);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X localApm->length = locallen;
- X localApm->sign = sign;
- X localApm->dp = apm->dp * SPECIAL_SCALE;
- X localApm->base = 10;
- X
- X for (n = 0; n < length; ++n) {
- X int tn = n * SPECIAL_SCALE;
- X int value = apm->data[n];
- X int newvalue = value / 10;
- X localApm->data[tn] = value - (newvalue * 10);
- X value = newvalue;
- X newvalue = value / 10;
- X localApm->data[tn + 1] = value - (newvalue * 10);
- X value = newvalue;
- X newvalue = value / 10;
- X localApm->data[tn + 2] = value - (newvalue * 10);
- X value = newvalue;
- X newvalue = value / 10;
- X localApm->data[tn + 3] = value - (newvalue * 10);
- X }
- X ercode = apm_assign(apm, localApm);
- X if (ercode >= APM_OK) {
- X ercode = APM_trim(apm, 1, 1);
- X }
- X return (ercode);
- X}
- X
- Xint
- XAPM_size(apm, len)
- XAPM apm;
- Xint len;
- X{
- X short *temp;
- X apm_errno = APM_OK;
- X
- X if (len < 0) {
- X return (APM_set_errno(APM_EPARM));
- X }
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (len > apm->alloclen || apm->alloclen < 1) {
- X if (len < 8) {
- X len = 8;
- X }
- X if (apm->alloclen < 1) {
- X temp = (short *)APM_alloc_mem(NULL, len,
- X sizeof (short));
- X }
- X else {
- X temp = (short *)APM_alloc_mem(apm->data, len,
- X sizeof (short));
- X }
- X if (temp == (short *)NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X apm->data = temp;
- X apm->alloclen = len;
- X }
- X
- X return (APM_OK);
- X}
- X
- Xint
- XAPM_parse_string(apm, string, base)
- XAPM apm;
- Xchar *string;
- Xshort base;
- X{
- X static char *localString = NULL;
- X static int localLen = 0;
- X int ercode;
- X int len;
- X int dp;
- X int special = 0;
- X short sign = 1;
- X char *temp;
- X short *bp;
- X char *tp;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (string == NULL) {
- X return (APM_set_errno(APM_ENULLVAL));
- X }
- X
- X if (base == 0) {
- X base = SPECIAL_BASE;
- X }
- X
- X ercode = APM_val_base(base);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X if (base == SPECIAL_BASE) {
- X special = 1;
- X base = 10;
- X }
- X
- X len = strlen(string);
- X if (localString == NULL || localLen < len + 1) {
- X int xlen = len + 1;
- X if (xlen < 16) {
- X xlen = 16;
- X }
- X localString = APM_alloc_mem(localLen < 1 ? NULL : localString,
- X xlen, sizeof (char));
- X if (localString == NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X localLen = xlen;
- X }
- X APM_copy_bytes(localString, string, len + 1);
- X
- X temp = APM_trim_string(APM_left_justify(localString, " \t"));
- X if (*temp == '-') {
- X sign = -1;
- X ++temp;
- X }
- X else if (*temp == '+') {
- X sign = 1;
- X ++temp;
- X }
- X
- X dp = APM_radix_pos(temp, base);
- X if (dp < 0) {
- X return (APM_set_errno(APM_EFMT));
- X }
- X
- X len = strlen(temp);
- X if (dp > 0) {
- X char *sp = &temp[dp];
- X do {
- X sp[-1] = *sp;
- X } while (*sp++ != '\0');
- X --len;
- X dp = len - (dp - 1);
- X }
- X
- X ercode = APM_size(apm, len);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X apm->base = base;
- X apm->length = len;
- X apm->dp = dp;
- X apm->sign = SIGNOF(sign);
- X for (bp = apm->data, tp = &temp[len]; tp-- > temp; ++bp) {
- X *bp = APM_get_digit(*tp, apm->base);
- X }
- X
- X if (special) {
- X ercode = APM_norm_to_spec(apm);
- X }
- X
- X if (ercode >= APM_OK) {
- X ercode = APM_trim(apm, 1, 1);
- X }
- X
- X return (ercode);
- X}
- X
- Xchar *
- XAPM_build_string(string, data, length, dpos)
- Xchar *string;
- Xshort *data;
- Xint length;
- Xint dpos;
- X{
- X short *bp;
- X int n = 0;
- X
- X for (bp = &(data[length]); bp-- > data; ++n) {
- X if (n == dpos) {
- X *string++ = '.';
- X }
- X *string++ = APM_digits[*bp];
- X }
- X return (string);
- X}
- X
- Xint
- XAPM_parse_long(apm, value, base)
- XAPM apm;
- Xlong value;
- Xshort base;
- X{
- X int ercode;
- X int n;
- X long temp;
- X
- X apm_errno = APM_OK;
- X
- X if (apm == (APM)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (base == 0) {
- X base = SPECIAL_BASE;
- X }
- X ercode = APM_val_base(base);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X apm->sign = 1;
- X apm->base = base;
- X apm->dp = 0;
- X
- X if (value < 0) {
- X apm->sign = -1;
- X value = -value;
- X }
- X
- X for (apm->length = 0, temp = value; temp != 0; temp /= base) {
- X ++(apm->length);
- X }
- X if (apm->length == 0) {
- X return (APM_OK);
- X }
- X
- X ercode = APM_size(apm, apm->length);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X
- X for (n = 0; n < apm->length; ++n) {
- X apm->data[n] = value % base;
- X value /= base;
- X }
- X
- X return (APM_OK);
- X}
- X
- Xshort
- XAPM_array_add(result, addend, length, base)
- Xshort *result;
- Xshort *addend;
- Xint length;
- Xshort base;
- X{
- X int n;
- X short tempval;
- X short carry = 0;
- X
- X for (n = 0; n < length; ++n) {
- X tempval = result[n] + carry + addend[n];
- X result[n] = tempval % base;
- X carry = tempval / base;
- X }
- X
- X return (carry);
- X}
- X
- Xshort
- XAPM_array_sub(result, subtrahend, length, base)
- Xshort *result;
- Xshort *subtrahend;
- Xint length;
- Xshort base;
- X{
- X int n;
- X short tempval;
- X short borrow = 0;
- X
- X for (n = 0; n < length; ++n) {
- X tempval = (result[n] + borrow) - subtrahend[n];
- X if (tempval < 0) {
- X result[n] = tempval + base;
- X borrow = -1;
- X }
- X else {
- X result[n] = tempval;
- X borrow = 0;
- X }
- X }
- X return (borrow);
- X}
- X
- Xshort
- XAPM_scalar_mul(result, multiplicand, length, multiplier, base)
- Xshort *result;
- Xshort *multiplicand;
- Xint length;
- Xshort multiplier;
- Xshort base;
- X{
- X int n;
- X long tempval;
- X short carry = 0;
- X
- X for (n = 0; n < length; ++n) {
- X tempval = multiplicand[n];
- X tempval *= multiplier;
- X tempval += carry;
- X result[n] = (short)(tempval % base);
- X carry = (short)(tempval / base);
- X }
- X return (carry);
- X}
- X
- Xint
- XAPM_scalar_div(result, dividend, length, dp, sign, base, divisor)
- XAPM result;
- Xshort *dividend;
- Xint length;
- Xint dp;
- Xshort sign;
- Xshort base;
- Xshort divisor;
- X{
- X static APM apmDividend = (APM)NULL;
- X static APM apmDivisor = (APM)NULL;
- X int ercode;
- X
- X apm_errno = APM_OK;
- X
- X if (result == (APM)NULL || dividend == (short *)NULL) {
- X return (APM_set_errno(APM_ENULL));
- X }
- X
- X if (apmDividend == (APM)NULL) {
- X apmDividend = APM_alloc();
- X if (apmDividend == (APM)NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X }
- X if (apmDivisor == (APM)NULL) {
- X apmDivisor = APM_alloc();
- X if (apmDivisor == (APM)NULL) {
- X return (APM_set_errno(APM_ENOMEM));
- X }
- X ercode = APM_size(apmDivisor, 1);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X apmDivisor->length = 1;
- X apmDivisor->dp = 0;
- X }
- X
- X ercode = APM_size(apmDividend, length);
- X if (ercode < APM_OK) {
- X return (ercode);
- X }
- X APM_copy_shorts(apmDividend->data, dividend, length);
- X
- X apmDividend->sign = sign;
- X apmDividend->length = length;
- X apmDividend->dp = dp;
- X apmDividend->base = base;
- X
- X if (divisor < 0) {
- X apmDivisor->data[0] = -divisor;
- X apmDivisor->sign = -1;
- X }
- X else {
- X apmDivisor->data[0] = divisor;
- X apmDivisor->sign = 1;
- X }
- X apmDivisor->base = base;
- X
- X return (apm_divide(result, length, (APM)NULL,
- X apmDividend, apmDivisor));
- X}
- X
- Xint
- XAPM_copy_bytes(to, from, num)
- Xregister char *to;
- Xregister char *from;
- Xint num;
- X{
- X register int n = num;
- X
- X if (to == NULL || from == NULL || num <= 0) {
- X return (0);
- X }
- X
- X if (to > from) {
- X to += n;
- X from += n;
- X while (n-- > 0) {
- X *(--to) = *(--from);
- X }
- X }
- X else if (to < from) {
- X while (n-- > 0) {
- X *to++ = *from++;
- X }
- X }
- X
- X return (num);
- X}
- X
- Xint
- XAPM_zero_bytes(to, num)
- Xregister char *to;
- Xint num;
- X{
- X register int n = num;
- X
- X if (to == NULL || num <= 0) {
- X return (0);
- X }
- X
- X while (n-- > 0) {
- X *to++ = 0;
- X }
- X
- X return (num);
- X}
- X
- Xint
- XAPM_copy_shorts(to, from, num)
- Xshort *to;
- Xshort *from;
- Xint num;
- X{
- X return (APM_copy_bytes((char *)to, (char *)from,
- X num * sizeof (short)) / sizeof (short));
- X}
- X
- Xint
- XAPM_zero_shorts(to, num)
- Xshort *to;
- Xint num;
- X{
- X return (APM_zero_bytes((char *)to,
- X num * sizeof (short)) / sizeof (short));
- X}
- X
- Xchar *
- XAPM_index(s, c)
- Xregister char *s;
- Xint c;
- X{
- X if (s != NULL) {
- X for (; *s != '\0'; ++s) {
- X if (*s == (char)c) {
- X return (s);
- X }
- X }
- X }
- X
- X return (NULL);
- X}
- X
- Xvoid
- XAPM_debug(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X char *format;
- X FILE *debug_file = apm_debug_file(NULL);
- X
- X if (debug_file == (FILE *)NULL) {
- X return;
- X }
- X
- X (void)apm_debug_file(debug_file);
- X
- X va_start(ap);
- X
- X format = va_arg(ap, char *);
- X if (format == NULL) {
- X return;
- X }
- X
- X vfprintf(debug_file, format, ap);
- X fflush(debug_file);
- X
- X va_end(ap);
- X}
- @\END_OF_FILE_utils.c
- else
- echo "shar: Will not over write utils.c"
- fi
- echo "Finished archive 4 of 5"
- # to concatenate archives, remove anything after this line
- exit 0
-